package cn.com.connext.scrm.service;

import cn.com.connext.scrm.domain.enumeration.DeleteStatus;
import cn.com.connext.scrm.domain.enumeration.MemberStatus;
import cn.com.connext.scrm.domain.master.Comment;
import cn.com.connext.scrm.domain.master.CommentLikes;
import cn.com.connext.scrm.domain.master.Member;
import cn.com.connext.scrm.domain.master.Note;
import cn.com.connext.scrm.repository.master.CommentLikesRepository;
import cn.com.connext.scrm.repository.master.CommentRepository;
import cn.com.connext.scrm.repository.master.MemberRepository;
import cn.com.connext.scrm.repository.master.NoteRepository;
import cn.com.connext.scrm.service.dto.*;
import cn.com.connext.scrm.service.mapper.CommentLikesMapper;
import cn.com.connext.scrm.service.mapper.CommentMapper;
import cn.com.connext.scrm.web.rest.errors.MyErrorCode;
import com.alibaba.fastjson.JSONObject;
import com.connext.common.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by YANG205 on 2018/6/27.
 */
@Service
@Transactional
public class CommentService extends BaseService<Comment, String> {

    private final Logger log = LoggerFactory.getLogger(CommentService.class);

    private final CommentRepository commentRepository;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private CommentLikesMapper commentLikesMapper;

    @Autowired
    private CommentLikesRepository commentLikesRepository;

    @Autowired
    private InteractiveRecordService interactiveRecordService;

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private NoteRepository noteRepository;

    @Autowired
    private WxAPIService wxAPIService;

    public CommentService(CommentRepository commentRepository) {
        super(commentRepository);
        this.commentRepository = commentRepository;
    }

    /**
     * 获取某条评论的详情
     *
     * @param id
     * @param userId
     * @return
     */
    public CommentDTO findOneCommentDTO(String id, String userId) {
        if (StringUtils.isEmpty(id)) {
            throw new ServiceException(MyErrorCode.ERROR_ID_EMPTY);
        }
        Comment comment = commentRepository.findOne(id);
        if (null == comment) {
            return null;
        } else if(comment.getDelete()){
            return null;
        } else {
            CommentDTO commentDTO = commentMapper.toDto(comment);
            if (StringUtils.isNotEmpty(userId)) {
                //判断当前小程序用户对该评论是否点赞过
                CommentLikes commentLikes = commentLikesRepository.findOneByCommentIdAndUserId(id, userId);
                if (null == commentLikes) {
                    commentDTO.setLike(false);
                } else {
                    commentDTO.setLike(true);
                }
                if (0 == comment.getReplyType()) {
                    List<Comment> comments = commentRepository.findAllReply(id);
                    List<CommentDTO> replyList = new ArrayList<>();
                    if (null != comments && comments.size() > 0) {
                        //存在二级评论
                        for (Comment item : comments) {
                            CommentDTO newCommentDTO = commentMapper.toDto(item);
//                            //判断当前小程序用户对该二级评论是否点赞过
//                            CommentLikes replyLikes = commentLikesRepository.findOne(item.getId(), userId);
//                            if (null == replyLikes) {
//                                commentDTO.setLike(false);
//                            } else {
//                                commentDTO.setLike(true);
//                            }
                            replyList.add(newCommentDTO);
                        }
                    }
                    commentDTO.setReplyList(replyList);
                }
            }
            return commentDTO;
        }
    }

    /**
     * 发布评论、回复评论
     *
     * @param commentVM
     * @return
     */
    public JsonResult createComment(CommentVM commentVM) {
        log.debug("REST to save {} : {}", getEntityName(), commentVM);
        JsonResult jsonResult = new JsonResult();
        JSONObject content = wxAPIService.msgSafeCheck(commentVM.getContent());
        log.info("contentCode:{}", content.get("errcode"));
        Integer code = (Integer) content.get("errcode");
        if (code != 0) {
            jsonResult.setState(1);
            jsonResult.setMessage("内容中包含敏感词，请修改");
            return jsonResult;
        }
        Member member = memberRepository.findOneByUnionId(commentVM.getUserId());
        if (null == member || member.getStatus() == MemberStatus.DELETED) {
            jsonResult.setState(1);
            jsonResult.setData(null);
            jsonResult.setMessage("当前用户不存在!");
            return jsonResult;
        } else {
            if (true == member.getBanned()) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("您已被禁言!");
                return jsonResult;
            }

            Note noteExsit = noteRepository.findOne(commentVM.getNoteId());
            if (null == noteExsit || noteExsit.getDeleteStatus() == DeleteStatus.DELETED) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("帖子不存在!");
                return jsonResult;
            }

            commentVM.setHeadImgUrl(member.getHeadImgUrl());
            commentVM.setUserName(member.getNickName());

            if (1 == commentVM.getReplyType()) {
                Member member1 = memberRepository.findOneByUnionId(commentVM.getReplyUserId());
                if (null != member1) {
                    commentVM.setReplyUserName(member1.getNickName());
                }
                //向上查询上一级评论
                Comment comment = commentRepository.findOne(commentVM.getReplyCommentId());
                //二级评论反查一级
                if (StringUtils.isEmpty(comment.getCommentId())) {
                    commentVM.setCommentId(comment.getId());
                } else {
                    //三级及其以下反查上一级
                    commentVM.setCommentId(comment.getCommentId());
                }

            }
            commentVM.setCreateTime(ZonedDateTime.now());
            Comment comment = commentMapper.toEntity(commentVM);
            comment.setDelete(false);
            comment = commentRepository.save(comment);

            String noteId = comment.getNoteId();
            String userId = comment.getUserId();
            String receiveUserId = comment.getReplyUserId();
            ZonedDateTime createTime = comment.getCreateTime();

            //添加一条互动
            InteractiveRecordDTO interactiveRecordDTO = new InteractiveRecordDTO();
            interactiveRecordDTO.setNoteId(noteId);
            interactiveRecordDTO.setContent(comment.getContent());
            interactiveRecordDTO.setCreateTime(createTime);
            interactiveRecordDTO.setUserId(userId);
            if (0 == comment.getReplyType()) {
                if (StringUtils.isNotEmpty(noteId)) {
                    Note note = noteRepository.findOne(noteId);
                    if (null != note) {
                        interactiveRecordDTO.setReceiveUserId(note.getUserId());
                    }
                }
            } else {
                interactiveRecordDTO.setReceiveUserId(receiveUserId);
            }
            interactiveRecordDTO.setInteractiveType(1);
            interactiveRecordDTO.setLookup(false);
            interactiveRecordService.createNew(interactiveRecordDTO);
            jsonResult.setState(0);
            jsonResult.setData(comment);
            jsonResult.setMessage("发表成功!");
            return jsonResult;
        }
    }

    /**
     * 评论点赞
     *
     * @param commentId
     * @param userId
     * @return
     */
    @Async
    public JsonResult likeComment(String commentId, String userId) {
        JsonResult jsonResult = new JsonResult();

        Comment comment = commentRepository.findOne(commentId);
        if (null == comment) {
            jsonResult.setState(1);
            jsonResult.setData(null);
            jsonResult.setMessage("评论不存在!");
            return jsonResult;
        } else if(comment.getDelete()){
            jsonResult.setState(1);
            jsonResult.setMessage("评论已删除");
            return jsonResult;
        } else {
            Note note = noteRepository.findOne(comment.getNoteId());
            if (null == note || note.getDeleteStatus() == DeleteStatus.DELETED) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("帖子不存在!");
                return jsonResult;
            }
        }

        if (StringUtils.isNotEmpty(userId)) {
            Member member = memberRepository.findOneByUnionId(userId);
            if (null == member || member.getStatus() == MemberStatus.DELETED) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("当前用户不存在!");
                return jsonResult;
            } else {
                if (true == member.getBanned()) {
                    jsonResult.setState(1);
                    jsonResult.setData(null);
                    jsonResult.setMessage("您已被禁言!");
                    return jsonResult;
                }
            }
        }

        CommentLikes commentLikes = commentLikesRepository.findOneByCommentIdAndUserId(commentId, userId);
        if (null == commentLikes) {
            CommentLikesDTO commentLikesDTO = new CommentLikesDTO();
            commentLikesDTO.setCommentId(commentId);
            commentLikesDTO.setUserId(userId);
            commentLikesDTO.setCreateTime(ZonedDateTime.now());
            CommentLikes newCommentLikes = commentLikesMapper.toEntity(commentLikesDTO);
            commentLikesRepository.save(newCommentLikes);
            //interactiveRecordService.create(comment.getNoteId(), userId, comment.getReplyUserId(), 2, 1, newCommentLikes.getCreateTime());
            InteractiveRecordDTO interactiveRecordDTO = new InteractiveRecordDTO();
            interactiveRecordDTO.setNoteId(comment.getNoteId());
            interactiveRecordDTO.setContent(comment.getContent());
            interactiveRecordDTO.setCreateTime(newCommentLikes.getCreateTime());
            interactiveRecordDTO.setUserId(userId);
            interactiveRecordDTO.setReceiveUserId(comment.getReplyUserId());
            interactiveRecordDTO.setInteractiveType(2);
            interactiveRecordDTO.setLookup(false);
            interactiveRecordService.createNew(interactiveRecordDTO);

            jsonResult.setState(0);
            jsonResult.setData(null);
            jsonResult.setMessage("点赞成功!");
            return jsonResult;
        } else {
            commentLikesRepository.delete(commentLikes);
            interactiveRecordService.delete(comment.getNoteId(), userId, comment.getReplyUserId(), 2);
            jsonResult.setState(0);
            jsonResult.setData(null);
            jsonResult.setMessage("取消点赞成功!");
            return jsonResult;
        }
    }

    /**
     * 获取某个帖子的所有一级评论
     *
     * @param noteId
     * @param userId
     * @return
     */
    public List<CommentDTO> getAllComment(String noteId, String userId) {
        List<Comment> comments = commentRepository.findByNoteId(noteId);
        if (null != comments && comments.size() > 0) {
            List<CommentDTO> commentDTOList = new ArrayList<>();
            for (Comment comment : comments) {
                CommentDTO commentDTO = findOneCommentDTO(comment.getId(), userId);
                commentDTOList.add(commentDTO);
            }
            return commentDTOList;
        } else {
            List<CommentDTO> commentDTOList = new ArrayList<>();
            return commentDTOList;
        }
    }

    public Specification<Comment> getWhereClause(final CommentDTO commentDTO) {
        Specification<Comment> specification = (Root<Comment> root, CriteriaQuery<?> query,
                                                CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            query.orderBy(cb.desc(root.get("createTime").as(ZonedDateTime.class)));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }

    public Page<CommentDTO> getAllComments(Pageable pageable, CommentDTO commentDTO) {
        if (null == commentDTO) {
            commentDTO = new CommentDTO();
        }
        Page<CommentDTO> result = commentRepository.findAll(getWhereClause(commentDTO), pageable);
        return result;
    }

    public void deleteById(String id) {
        Comment comment = commentRepository.findOne(id);
        if (comment == null || comment.getDelete()){
            throw new ServiceException(MyErrorCode.ERROR_DATA_ISNULL);
        }
        comment.setDelete(true);
        comment.setDeleteTime(new Date());
        commentRepository.save(comment);
    }
}
